﻿using Aker;
using Aker.DevTeam;
using Aker.Properties;
using DevExpress.LookAndFeel;
using DevExpress.Utils.Paint;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace Extensions
{
    public static class GridViewExtensions
    {
        public static void Init(this GridView gridview, BindingSource bs, bool initialized = false)
        {
            InitBase(gridview, bs, initialized);
        }

        public static void Init(this GridView gridview, DataTable dt, bool initialized = false)
        {
            InitBase(gridview, dt, initialized);
        }

        public static void InitBase(this GridView gridview, object bs, bool initialized = false)
        {
            try
            {
                gridview.BeginUpdate();
                gridview.Columns.Clear();

                if (gridview.ViewCaption != "")
                    gridview.OptionsView.ShowViewCaption = true;
                else
                    gridview.OptionsView.ShowViewCaption = false;

                //gridview.ViewCaption = gridview.Name.Replace("gv", "");                
                //gridview.OptionsView.ShowViewCaption = true;


                gridview.GridControl.DataSource = null;
                gridview.GridControl.DataSource = bs;
                gridview.PopulateColumns();

                foreach (DevExpress.XtraGrid.Columns.GridColumn col in gridview.Columns)
                    if (col.ColumnType == typeof(DateTime))
                    {
                        col.OptionsFilter.FilterPopupMode = FilterPopupMode.DateSmart;
                        col.FilterMode = DevExpress.XtraGrid.ColumnFilterMode.Value;
                        col.OptionsFilter.ImmediateUpdateAutoFilter = true;
                        col.OptionsFilter.ImmediateUpdatePopupDateFilterOnCheck = DevExpress.Utils.DefaultBoolean.True;
                        col.OptionsFilter.ImmediateUpdatePopupDateFilterOnDateChange = DevExpress.Utils.DefaultBoolean.True;
                    }

                gridview.OptionsView.EnableAppearanceEvenRow = false;
                gridview.OptionsView.EnableAppearanceOddRow = false;


                gridview.BestFitMaxRowCount = 200;
                gridview.GridControl.ShowOnlyPredefinedDetails = true;
                gridview.HorzScrollStep = 50;

                gridview.OptionsBehavior.CopyToClipboardWithColumnHeaders = false;
                gridview.OptionsBehavior.ImmediateUpdateRowPosition = false;
                gridview.OptionsBehavior.KeepFocusedRowOnUpdate = true;
                gridview.OptionsFilter.AllowColumnMRUFilterList = true;
                gridview.OptionsFilter.ShowAllTableValuesInCheckedFilterPopup = false;
                gridview.OptionsFilter.ShowAllTableValuesInFilterPopup = false;
                gridview.OptionsHint.ShowColumnHeaderHints = true;
                gridview.OptionsMenu.EnableColumnMenu = true;
                gridview.OptionsMenu.ShowDateTimeGroupIntervalItems = true;
                gridview.OptionsNavigation.UseOfficePageNavigation = true;
                gridview.OptionsSelection.MultiSelect = true;
                gridview.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CellSelect;
                gridview.OptionsView.ColumnAutoWidth = false;
                gridview.OptionsView.RowAutoHeight = true;
                gridview.OptionsView.ShowAutoFilterRow = true;
                gridview.OptionsView.ShowDetailButtons = false;
                gridview.OptionsView.ShowGroupPanel = false;


                if (gridview.Columns["Thumbnail"] != null)
                {
                    GridColumn colPhoto = gridview.Columns["Thumbnail"];

                    colPhoto.ColumnEdit = new RepositoryItemPictureEdit();
                    colPhoto.UnboundType = DevExpress.Data.UnboundColumnType.Object;

                    (colPhoto.ColumnEdit as RepositoryItemPictureEdit).SizeMode = PictureSizeMode.Clip;
                    (colPhoto.ColumnEdit as RepositoryItemPictureEdit).NullText = " ";

                    colPhoto.AppearanceCell.Options.UseTextOptions = true;
                    colPhoto.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center;


                    //////gridview.CustomUnboundColumnData -= new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(gvProduct_CustomUnboundColumnData);
                    gridview.RowCellClick -= new RowCellClickEventHandler(gridview_RowCellClick);
                    gridview.MouseMove -= new MouseEventHandler(gridview_MouseMove);

                    //////gridview.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(gvProduct_CustomUnboundColumnData);
                    //////gridview.RowCellClick += new RowCellClickEventHandler(gridview_RowCellClick);
                    //////gridview.MouseMove += new MouseEventHandler(gridview_MouseMove);

                    gridview.Columns["Thumbnail"].Caption = "Görsel";
                    //gridview.Columns["Thumbnail"].Width = 48;
                    gridview.Columns["Thumbnail"].OptionsColumn.AllowEdit = false;
                    gridview.Columns["Thumbnail"].OptionsColumn.ReadOnly = true;

                    gridview.CalcRowHeight -= gridview_CalcRowHeight;
                    gridview.CustomDrawCell -= XForm_CustomDrawCell;
                    gridview.RowCellClick -= gridview_RowCellClick;
                    gridview.MouseMove -= gridview_MouseMove;

                    gridview.CalcRowHeight += gridview_CalcRowHeight;
                    gridview.CustomDrawCell += XForm_CustomDrawCell;
                    gridview.RowCellClick += gridview_RowCellClick;
                    gridview.MouseMove += gridview_MouseMove;
                }

                foreach (GridColumn gc in gridview.Columns)
                {
                    string colName = gc.FieldName.ToLower();
                    if (colName == "modifiedon" || colName == "ts" || colName == "deleted")
                        gc.Visible = false;
                    else
                        gc.Visible = true;
                }

                gridview.LoadLayout();


            }
            catch (Exception Ex)
            {
                throw (Ex);
            }
            finally
            {
                gridview.EndUpdate();
            }

            gridview.Appearance.EvenRow.BackColor = (UserLookAndFeel.Default.SkinName == "Office 2007 Black" ? System.Drawing.Color.WhiteSmoke : System.Drawing.Color.FromArgb(250, 245, 245));
        }


        public static void LoadLayout(this GridView gridview)
        {
            GridManager gm = GridManager.GetManager(gridview);
            if (gm.GridId == -1)
                return;

            DataTable dt = Data.DM.ExecuteDataTable("GetGrid", gm.GridId, AppSession.UserInfo.UserId);
            if (dt.Rows.Count > 0)
            {
                DataRow dr = dt.Rows[0];
                string pairs = dr["Captions"].ToStringNN();

                foreach (GridColumn gc in gridview.Columns)
                    gc.Visible = false;

                int i = 0;
                foreach (string pair in pairs.Split(",".ToCharArray()))
                {
                    string[] vals = pair.Split(":".ToCharArray());
                    string colName = vals[0];
                    string caption = vals[1];
                    if (gridview.Columns[colName] != null)
                    {
                        gridview.Columns[colName].VisibleIndex = i++;
                        gridview.Columns[colName].Caption = caption;

                    }
                }
            }
        }

        public static void SaveLayout(this GridView gridview, object sender, EventArgs e)
        {
            GridManager gm = GridManager.GetManager(gridview);
            if (gm.GridId == -1)
            {
                XtraMessageBox.Show("Bu özelliğin eklenmesi için yazılım ekibine bildiri de bulunun.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            List<string> captions = new List<string>();
            foreach (GridColumn gc in gridview.VisibleColumns)
            {
                string fieldName = gc.FieldName;
                string caption = gc.Caption;
                if (caption == "")
                    caption = fieldName;

                captions.Add(fieldName + ":" + caption);
            }


            Data.DM.ExecuteNonQuery("SetGrid", gm.GridId, string.Join(",", captions), AppSession.UserInfo.UserId);
            DevExpress.XtraEditors.XtraMessageBox.Show("Düzen kaydedildi.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        public static void DelLayout(this GridView gridview, object sender, EventArgs e)
        {
            GridManager gm = GridManager.GetManager(gridview);
            if (gm.GridId == -1)
            {
                XtraMessageBox.Show("Kayıtlı bir düzen yok.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }


            Data.DM.ExecuteNonQuery("DelGrid", gm.GridId, AppSession.UserInfo.UserId);
            XtraMessageBox.Show("Düzen temizlendi. Formu kapatıp açabilirsiniz.", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }



        private static void gridview_MouseMove(object sender, MouseEventArgs e)
        {
            GridView view = sender as GridView;
            GridHitInfo info = view.CalcHitInfo(new Point(e.X, e.Y));

            if (info.InRowCell && info.Column.FieldName == "Thumbnail" && info.RowHandle > -1)
            {
                DataRow dr = view.GetDataRow(info.RowHandle);
                if (dr.Table.Columns.Contains("ProductId"))
                {
                    int productId = dr["ProductId"].ToIntNN();
                    AkerDB.ProductRow product = Data.DB.Product.FindByProductId(productId);
                    if (product != null && !product.IsThumbnailNull())
                        view.GridControl.Cursor = Cursors.Hand;
                    else
                        view.GridControl.Cursor = Cursors.Default;
                }
            }
            else
                view.GridControl.Cursor = Cursors.Default;
        }

        private static void gridview_RowCellClick(object sender, RowCellClickEventArgs e)
        {
            GridView view = sender as GridView;

            if (e.RowHandle > -1)
            {
                if (e.Column.FieldName == "Thumbnail")
                {
                    int id = -1;
                    if (view.Columns["ProductId"] != null)
                        id = view.GetDataRow(e.RowHandle)["ProductId"].ToIntNN();
                    else if (view.Columns["BazProductId"] != null)
                        id = view.GetDataRow(e.RowHandle)["BazProductId"].ToIntNN();
                    if (id > -1)
                    {
                        AkerDB.ProductRow product = Data.DB.Product.FindByProductId(id);
                        if (product != null && !product.IsThumbnailNull())
                        {
                            ImageViewer iv = new ImageViewer(id);
                            iv.WindowState = FormWindowState.Maximized;
                            iv.ShowDialog();
                        }
                    }
                }
            }
        }


        public static void gridview_CalcRowHeight(object sender, RowHeightEventArgs e)
        {
            if (e.RowHandle > -1)
            {
                e.RowHeight = 48;
            }
            //if (e.RowHeight < notready.Height)
            //    e.RowHeight = notready.Height;
        }

        public static void XForm_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
        {
            if (e.RowHandle > -1)
                if (e.Column.FieldName == "Thumbnail" || e.Column.FieldName == "Photo")
                {
                    if (e.CellValue != DBNull.Value && e.CellValue == null)
                    {
                        e.Handled = false;
                    }
                    else
                    {
                        DataRow dr = (sender as GridView).GetDataRow(e.RowHandle);
                        if (dr.Table.Columns.Contains("ProductId"))
                        {
                            int productId = dr["ProductId"].ToIntNN();
                            AkerDB.ProductRow product = Data.DB.Product.FindByProductId(productId);
                            if (product != null && !product.IsThumbnailNull())
                            {
                                MemoryStream ms = new MemoryStream(product.Thumbnail);
                                e.Graphics.DrawImage(Image.FromStream(ms), e.Bounds.X + 1, e.Bounds.Y);
                                e.Handled = true;
                                return;
                            }
                        }
                    }

                    //e.DisplayText = "X";
                    if (Data.IsLookupInitialized)
                        e.Graphics.DrawImageUnscaled(Resources.ResimYok32, e.Bounds.X + 8, e.Bounds.Y + 8);
                    else
                        e.Graphics.DrawImageUnscaled(Resources.Yukleniyor, e.Bounds.X, e.Bounds.Y);

                    e.Handled = true;
                }
        }


        public static void AddSummary(this GridView gridView, params string[] columnNames)
        {
            gridView.OptionsView.ShowFooter = true;
            foreach (GridColumn col in gridView.Columns)
                if (col.Visible == true)
                {
                    col.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Count;
                    col.SummaryItem.DisplayFormat = "{0:#,##0} records";
                    break;
                }

            foreach (string columnName in columnNames)
            {
                GridColumn gc = gridView.Columns[columnName];

                if (gc != null)
                {
                    gc.SummaryItem.FieldName = columnName;
                    gc.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum;
                    gc.SummaryItem.DisplayFormat = "{0:#,##0.#}";
                }
                else
                    AppSession.MainForm.Notify("--");
            }
        }

        public static void SetVisibleIndex(this GridView gridView, params string[] orderedColumnNames)
        {
            foreach (GridColumn gc in gridView.Columns)
                gc.Visible = false;

            int index = 0;
            foreach (string col in orderedColumnNames)
            {
                GridColumn gc = gridView.Columns[col];
                //gc.Visible = true;
                if (gc != null)
                    gc.VisibleIndex = index++;
            }
        }

        public static void SetCaptions(this GridView gridView, params string[] pairs)
        {
            string problematicCols = string.Empty;
            foreach (string pair in pairs)
            {
                try
                {
                    string[] vals = pair.Split(':');
                    string colName = vals[0];//.Trim();
                    string caption = vals[1];//.Trim();
                    gridView.Columns[colName].Caption = caption;
                }
                catch
                {
                    problematicCols += pair + ",";
                }
            }
        }

        public static void EndEditing(this GridView gridView)
        {
            gridView.CloseEditor();
            gridView.UpdateCurrentRow();

        }

        public static void MakeColumnsReadOnly(this GridView gridView, params string[] columnNames)
        {
            foreach (string columnName in columnNames)
                gridView.Columns[columnName].OptionsColumn.AllowEdit = false;
        }

        public static void SetGridId(this GridView gridView, int Id)
        {
            GridManager gm = GridManager.GetManager(gridView);
            gm.GridId = Id;
        }

        public static void MakeReadOnly(this GridView gridView, params string[] ExceptTheseColumns)
        {
            foreach (GridColumn gc in gridView.Columns)
                gc.OptionsColumn.AllowEdit = ExceptTheseColumns.Any(gc.FieldName.Contains);

            //gridView.OptionsBehavior.Editable = false;
        }

        public static void MakeEditable(this GridView gridView, params string[] ExceptTheseColumns)
        {
            foreach (GridColumn gc in gridView.Columns)
                gc.OptionsColumn.AllowEdit = !ExceptTheseColumns.Any(gc.FieldName.Contains);

            //gridView.OptionsBehavior.Editable = true;
        }

        public static void MakeColumnInvisible(this GridView gridView, params string[] columnNames)
        {
            string problematicCols = string.Empty;
            if (columnNames.Length == 0)
            {
                foreach (GridColumn gc in gridView.Columns)
                    gc.Visible = false;
            }
            else
            {
                foreach (string columnName in columnNames)
                {
                    try
                    {
                        gridView.Columns[columnName].Visible = false;
                    }
                    catch
                    {
                        problematicCols += columnName + ",";
                    }
                }
            }
        }

        public static void EnableComplexFiltering(this GridView gridView, params string[] colNames)
        {
            gridView.ColumnFilterChanged += gv_ColumnFilterChanged;
            gridView.CustomDrawCell += gridView_CustomDrawCell;
            gridView.Tag = colNames;
        }


        static void gridView_CustomDrawCell(object sender, RowCellCustomDrawEventArgs e)
        {
            GridView gv = sender as GridView;

            if (e.RowHandle < 0) // && e.RowHandle != DevExpress.XtraGrid.GridControl.AutoFilterRowHandle)
            {
                e.Handled = false;
                return;
            }

            string[] colNames = (string[])gv.Tag;

            string colName = e.Column.FieldName.ToStringNN();
            if (colName == "")
                return;

            if (colNames.Contains(colName))
            {
                //if (e.RowHandle == DevExpress.XtraGrid.GridControl.AutoFilterRowHandle)
                //{
                //     string a = e.Column.FilterInfo.DisplayText;
                //        XPaint.Graphics.DrawString(e.Cache, a, new Font(gv.Appearance.Row.Font, FontStyle.Regular), Brushes.Black, e.Bounds, StringFormat.GenericDefault);
                //        e.Handled = true;
                //        return;
                //}
                //else
                {
                    string[] vals = gv.Columns[colName].FilterInfo.FilterString.Split('(', ')');
                    List<string> filters = new List<string>();
                    foreach (string val in vals)
                        if (!val.Contains("Conta"))
                        {
                            string filter = val.Replace("[" + colName + "], ", "").Replace("'", "");
                            if (filter != "")
                                filters.Add(filter);
                        }

                    foreach (string filter in filters)
                    {
                        int filterTextIndex = e.DisplayText.IndexOf(filter, StringComparison.CurrentCultureIgnoreCase);
                        if (filterTextIndex == -1)
                            return;

                        XPaint.Graphics.DrawMultiColorString(e.Cache, e.Bounds, e.DisplayText, filter, e.Appearance, Color.Black, Color.Gold, false, filterTextIndex);
                        e.Handled = true;
                    }
                }
            }
            else
                e.Handled = false;
        }



        static void gv_ColumnFilterChanged(object sender, EventArgs e)
        {
            GridView gv = sender as GridView;
            string[] colNames = (string[])gv.Tag;
            gv.ColumnFilterChanged -= gv_ColumnFilterChanged;

            foreach (string colName in colNames)
            {
                if (gv.Columns[colName] == null)
                    continue;

                string filter = gv.Columns[colName].FilterInfo.Value.ToStringNN();

                if (filter != "")
                {
                    List<string> newFilter = new List<string>();
                    foreach (string item in filter.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
                        newFilter.Add("Contains([" + colName + "], '" + item + "')");

                    string lastFilter = string.Join(" and ", newFilter);
                    ColumnFilterInfo ci = gv.Columns[colName].FilterInfo;
                    ColumnFilterInfo ciNew = new ColumnFilterInfo(lastFilter, lastFilter, filter, ColumnFilterType.AutoFilter);

                    gv.Columns[colName].FilterInfo = ciNew;

                    //new DevExpress.XtraGrid.Columns.ColumnFilterInfo(lastFilter, filter);

                }
            }
            gv.ColumnFilterChanged += gv_ColumnFilterChanged;
        }

        public static void FormatAsNumberBase(GridView gridView, int decimalPoints, params string[] columnNames)
        {
            string problematicCols = string.Empty;

            foreach (string columnName in columnNames)
            {
                if (gridView.Columns.Contains(gridView.Columns[columnName]))
                {
                    GridColumn col = gridView.Columns[columnName];
                    col.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric;
                    string format = "#,##0.";
                    for (int i = 0; i < decimalPoints; i++)
                        format += "0";

                    if (format.EndsWith("."))
                        format = format.Substring(0, format.Length - 1);
                    col.DisplayFormat.FormatString = format + ";-" + format + "; ";

                    //col.DisplayFormat.FormatString = "{0:n2}";
                    //TODO: col.DisplayFormat.FormatString = "#,##0.0;-#,##0.0;";

                    col.FilterMode = DevExpress.XtraGrid.ColumnFilterMode.Value;

                    //col.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric;
                    //col.DisplayFormat.FormatString = "#,###";
                    //col.FilterMode = DevExpress.XtraGrid.ColumnFilterMode.Value;

                    //col.ColumnEdit = new RepositoryItemCalcEdit();
                    col.ColumnEdit = MaskedNumeric(decimalPoints != 1 ? decimalPoints : 2);
                }
                else
                    problematicCols += columnName + ",";
            }
            //gridView.BestFitColumns();

            if (problematicCols != string.Empty)
            {
                ApplicationException aex = new ApplicationException("Sütun formatlamada hata! Bulunamayan sütun ismi: " + problematicCols.Substring(0, problematicCols.Length - 1));
                //LogManager.LogToDB(aex);
                //LogManager.Notify(aex);
            }

        }

        public static void FormatAsDateTime(this GridView gridView, params string[] columnNames)
        {
            string problematicCols = string.Empty;

            foreach (string columnName in columnNames)
            {
                try
                {
                    GridColumn col = gridView.Columns[columnName];
                    col.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime;
                    col.DisplayFormat.FormatString = "dd.MM.yyyy HH:mm:ss";
                }
                catch
                {
                    problematicCols += columnName + ",";
                }
            }
            //gridView.BestFitColumns();

            if (problematicCols != string.Empty)
            {
                ApplicationException aex = new ApplicationException("Sütun tarih formatlamada hata! Bulunamayan sütun ismi : " + problematicCols.Substring(0, problematicCols.Length - 1));
                //LogManager.LogToDB(aex);
                //LogManager.Notify(aex);
            }
        }

        public static void FormatAsNumber(this GridView gridView, params string[] columnNames)
        {
            FormatAsNumberBase(gridView, 2, columnNames);
        }

        public static void FormatAsNumber(this GridView gridView, int decimalPoints, params string[] columnNames)
        {
            FormatAsNumberBase(gridView, decimalPoints, columnNames);
        }

        public static RepositoryItemTextEdit MaskedNumeric(int digits = 0)
        {
            RepositoryItemTextEdit ri = new RepositoryItemTextEdit();
            ri.AutoHeight = false;
            ri.Mask.EditMask = "f" + digits.ToString();
            ri.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.Numeric;
            //ri.Mask.UseMaskAsDisplayFormat = true;            
            return ri;
        }

        public static void MakeRowSelectable(this GridView gridView)
        {
            gridView.OptionsSelection.EnableAppearanceFocusedCell = false;
            gridView.OptionsSelection.EnableAppearanceFocusedRow = true;
            gridView.OptionsSelection.MultiSelect = false;
        }

        public static void VeriyiGuncelle(this GridView gridView, DataTable dt)
        {
            VeriyiGuncelle(gridView, true, dt);
        }

        public static void VeriyiGuncelle(this GridView gridView, bool ClearOldData, DataTable dt)
        {
            DataSet dsRoot = gridView.Dataset();
            if (ClearOldData)
                dsRoot.Tables[dt.TableName].Clear();
            dsRoot.Merge(dt);
            //gridView.BestFitColumns();
        }

        public static void VeriyiGuncelle(this GridView gridView, string SPName, params object[] SPParams)
        {
            VeriyiGuncelle(gridView, true, SPName, SPParams);
        }

        public static void VeriyiGuncelle(this GridView gridView, bool ClearOldData, string SPName, params object[] SPParams)
        {
            DataSet dsRoot = gridView.Dataset();
            if (ClearOldData)
                dsRoot.Clear();

            DataSet dsNew = Data.DM.ExecuteDataSet(SPName, SPParams);

            dsRoot.Merge(dsNew);
            //gridView.BestFitColumns();
        }

        public static DataSet Dataset(this GridView gvMaster)
        {
            DataSet dsRoot = null;
            BindingSource bsRoot = (BindingSource)gvMaster.DataSource;

            int dtSourceIndex = -1;
            while (true)
            {
                dtSourceIndex++;
                if (dtSourceIndex > 10)
                {
                    //Pratikte 10 grid birbirine bağlanmış olmamalıdır ;
                    throw new ApplicationException("Binding kullanım hatası !!!");
                }
                if (bsRoot.DataSource.GetType() == typeof(DataSet))
                {
                    dsRoot = (DataSet)bsRoot.DataSource;
                    return dsRoot;
                }
                else
                {
                    bsRoot = (BindingSource)bsRoot.DataSource;
                }
            }
        }

    }
}